﻿using Aribaccio;
using Aribaccio.Core;
using Aribaccio.Device;
using BDPAutodetect.Device;
using BDPAutodetect.Simcore;
using CommunityToolkit.Mvvm.Input;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BDPAutodetect.Simulator
{
    /// <summary>
    /// 
    /// </summary>
    public partial class SimulatorViewModel : ObservableModel
    {
        protected object _locker = new object();
        protected const int TransLogMaxCount = 1000;
        protected TaskScheduler syncTaskMessageIn = TaskScheduler.FromCurrentSynchronizationContext();
        protected TaskScheduler syncTaskMessageOut = TaskScheduler.FromCurrentSynchronizationContext();
        /// <summary>
        /// 设备仿真实例
        /// </summary>
        protected DeviceSimulatorBase? DeviceSimulator { get; set; }
        /// <summary>
        /// 日志信息集合
        /// </summary>
        public ObservableCollection<TransLogItem> TransLogItems { get; set; }

        /// <summary>
        /// 是否连接打开
        /// </summary>
        public bool IsConnected => this.DeviceSimulator?.IsOpen ?? false;
        /// <summary>
        /// 仿真设备名称
        /// </summary>
        public string DeviceName => this.DeviceSimulator?.DeviceName ?? string.Empty;
        /// <summary>
        /// 仿真设备地址端口
        /// </summary>
        public string DeviceAddressPort => this.DeviceSimulator?.DeviceAddressPort ?? string.Empty;
        /// <summary>
        /// 设备指令数据
        /// </summary>
        public List<DeviceCommandData> DeviceCommandDatas => this.DeviceSimulator?.DeviceCommandDatas ?? new List<DeviceCommandData>();

        /// <summary>
        /// 构造函数
        /// </summary>
        public SimulatorViewModel(DeviceType argDeviceType, DeviceModule argDeviceModule)
        {
            this.TransLogItems = new ObservableCollection<TransLogItem>();
            //从容器中获取-检测设备管理初始化
            var deviceSimulatorMgr = ContainerManager.Instance.GetContainerServiceRequired<DeviceSimulatorManager>();
            if (deviceSimulatorMgr != null)
            {
                this.DeviceSimulator = deviceSimulatorMgr.GetDetectDevice(argDeviceType, argDeviceModule);
            }
            if (this.DeviceSimulator != null)
            {
                this.DeviceSimulator.MessageIn += OnMessageIn;
                this.DeviceSimulator.MessageOut += OnMessageOut;
            }
        }

        /// <summary>
        /// 清除日志命令事件
        /// </summary>
        [RelayCommand]
        public void ExecuteClearLog()
        {
            this.TransLogItems.Clear();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="argMessage"></param>
        protected void OnMessageIn(string argMessage)
        {
            Task.Factory.StartNew(() =>
            {
                if (string.IsNullOrEmpty(argMessage)) return;
                this.AddTransLog(new TransLogItem()
                {
                    Incoming = argMessage.Replace("\r", "<cr>").Replace("\n", "<lf>"),
                    OccurTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")
                });
            }, new CancellationTokenSource().Token, TaskCreationOptions.None, syncTaskMessageIn);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="argMessage"></param>
        protected void OnMessageOut(string argMessage)
        {
            Task.Factory.StartNew(() =>
            {
                if (string.IsNullOrEmpty(argMessage)) return;
                this.AddTransLog(new TransLogItem()
                {
                    Outgoing = argMessage.Replace("\r", "<cr>").Replace("\n", "<lf>"),
                    OccurTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")
                });
            }, new CancellationTokenSource().Token, TaskCreationOptions.None, syncTaskMessageOut);
        }

        /// <summary>
        /// 添加日志信息
        /// </summary>
        /// <param name="argLogItem"></param>
        protected void AddTransLog(TransLogItem argLogItem)
        {
            lock (_locker)
            {
                if (this.TransLogItems.Count > TransLogMaxCount)
                {
                    this.TransLogItems.RemoveAt(this.TransLogItems.Count - 1);
                }
                this.TransLogItems.Insert(0, argLogItem);
            }
        }
    }
}
